#!BPY

"""
Name: 'Import 2D Cutout Images'
Blender: 244
Group: 'Misc'
Tooltip: 'Import alpha enabled .png files and UV map them'
"""

__author__ = "Kevin Morgan (forTe)"
__url__ = ("Home page, http://gamulabs.freepgs.com")
__version__ = "1.1"
__bpydoc__ = """\
This Script will take an image with an alpha channel (or one without) and
UV map it to a plane sharing the same width to height ratio as the image.
Import options allow simple materials to be assigned to the plane as well.
<br><br>
Imports can be single images or whole directories of images depending on the chosen
option.
"""

#This program imports a single image or series of images stored in a directory
#And then proceeds to map them to planes. The script was originally written
#to help speed up the process of 2D image animation in Blender

####################################################
#Copyright (C) 2007: Kevin Morgan <ivan.carzy _at_ gmail.com>
####################################################
#-------------GPL LICENSE BLOCK-------------
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hopes that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of 
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program. If not, see <http://www.gnu.org/licenses>.
####################################################

##################################
#V1.0
#Basic Functionality
#Published June 28, 2007
##################################
#V1.1
#Added Support for enabling viewport transparency
#Added more options to the UI for materials
#Added Proportionality code (Pixels per unit)
#Added GPL License Block
#Published June 29, 2007
##################################


import Blender
from Blender import BGL, Draw, Image, Material, Mesh, Object, Scene, Texture, Window
from Blender.Mathutils import *

#Global Variables
NO_EVT = 1000
SINGLE_IMG = 1
DIRECT_IMG = 2
CLR_PATH = 3
DO_SCRIPT = 4
CHG_EXT = 5
EXIT = 6
REDRAW =7

#Button Initializations

#Import Buttons
ImagePath = Draw.Create('')
imgExt = Draw.Create('.png')

#Material Buttons
matColR = Draw.Create(0.8)
matColG = Draw.Create(0.8)
matColB = Draw.Create(0.8)
matAlpha = Draw.Create(0.0)
matRef = Draw.Create(1.0)
matSpec = Draw.Create(0.0)
matHard = Draw.Create(50)
matZtransp = Draw.Create(1)
matShadeless = Draw.Create(0)
texCol = Draw.Create(1)
texAlpha = Draw.Create(1)
imgUseAlpha = Draw.Create(1)
imgCalcAlpha = Draw.Create(0)

#View and Creation Buttons
viewTransp = Draw.Create(1)
pixelsPerUnit = Draw.Create(500)

#Global path list for import
pathList = []
######################
def main(ImagePath):
	global matColR, matColG, matColB, matAlpha, matRef, matSpec, matHard
	global matZtransp, matShadeless
	global texCol, texAlpha, imgUseAlpha, imgCalcAlpha
	global viewTransp, pixelsPerUnit
	###################################################
	#Create an Image object to hold Image
	img = Image.Load(ImagePath)
	name = Blender.sys.makename(ImagePath, strip = 1)
	##################################################	
	#Create a Plane with Aspect Ratio of Image
	
	me = Mesh.New(name)
	
	imgDimensions = img.getSize()
	
	dim = [float(i) / pixelsPerUnit.val for i in imgDimensions]
	
	#Max distance from origin in any direction will be 1 blender unit
	vert = me.verts
	vert.extend(dim[0], dim[1], 0)
	vert.extend(-dim[0], dim[1], 0)
	vert.extend(-dim[0], -dim[1], 0)
	vert.extend(dim[0], -dim[1], 0)
	
	me.faces.extend(vert[0], vert[1], vert[2], vert[3])

	#Do UV Stuff
	me.faces[0].image = img
	me.faces[0].uv = [Vector(1.0, 1.0), Vector(0.0, 1.0), Vector(0.0, 0.0), Vector(1.0, 0.0)]
	
	#Make face transparent in viewport
	if viewTransp.val:
		me.faces[0].transp = Mesh.FaceTranspModes.ALPHA
	##################################################
	#Do Material/Texture Assignments
	#Make Material
	mat = Material.New(name)
	
	#Set Color
	mat.rgbCol = [matColR.val, matColG.val, matColB.val]
	
	#Set Shading Info
	if matShadeless.val:
		mat.mode |= Material.Modes.SHADELESS
		
	else:
		mat.setRef(matRef.val)
		mat.setSpec(matSpec.val)
		mat.setHardness(matHard.val)
	
	#Set Transparency
	mat.setAlpha(matAlpha.val)
	
	if matZtransp.val:
		mat.mode |= Material.Modes.ZTRANSP
	
	#Makes an image texture
	tex = Texture.New(name)
	tex.setType('Image')
	tex.setImage(img)	
	
	if imgUseAlpha.val:
		tex.useAlpha = Texture.ImageFlags.USEALPHA
		
	if imgCalcAlpha.val:
		tex.calcAlpha = Texture.ImageFlags.CALCALPHA
	
	mat.setTexture(0, tex)
	mtex = mat.getTextures()[0]
	mtex.texco = Texture.TexCo.UV
	
	if texCol.val:
		mtex.mapto |= Texture.MapTo.COL
		
	if texAlpha.val:
		mtex.mapto |= Texture.MapTo.ALPHA
	
	#Assign material to mesh
	me.materials += [mat]
	##################################################	
	#Pack into Object
	ob = Object.New('Mesh', name)
	ob.link(me)
	scn = Scene.GetCurrent()
	scn.objects.link(ob)
	
	return

def setSinglePath(filename):
	global ImagePath, pathList
	ImagePath.val = filename
	pathList.append(filename)
	return
	
def setDirPath(filename):
	global ImagePath, pathList, imgExt
	
	try:
		import os
	except:
		print "Full, updated install of python required for script to work"
		Draw.Exit()
		
	path = Blender.sys.dirname(filename)
	ImagePath.val = path
	
	for f in os.listdir(path):
		if f[-4:] == imgExt.val:
			pathList.append(os.path.join(path, f))
				
	return

def changeExtension():
	global ImagePath, pathList
	
	try:
		import os
	except:
		print "Full, updated install of python required for script to work"
		Draw.Exit()
		
	pathList = []
	
	for f in os.listdir(ImagePath.val):
		if f[-4:] == imgExt.val:
			pathList.append(os.path.join(ImagePath.val, f))
	
def event(evt, val):
	if evt == Draw.ESCKEY:
		Draw.Exit()
		return

def bevent(evt):
	global NO_EVT, SINGLE_IMG, DIRECT_IMG, CLR_PATH, DO_SCRIPT, CHG_EXT, EXIT
	global ImagePath, pathList, REDRAW
	if evt == NO_EVT:
		pass
	
	elif evt == SINGLE_IMG:
		Window.FileSelector(setSinglePath, 'Image')
		Draw.Redraw()
		
	elif evt == DIRECT_IMG:		
		Window.FileSelector(setDirPath, 'Directory')
		Draw.Redraw()
		
	elif evt == CLR_PATH:
		ImagePath.val = ''
		Draw.Redraw()
		
	elif evt == DO_SCRIPT:
		total = len(pathList)
		for id,path in enumerate(pathList):
			main(path)
			Window.DrawProgressBar(float(id)/total, "Imported %i of %i images" %(id+1, total))
			Blender.Redraw()
		Window.DrawProgressBar(1.0, "Finished Importing")
			
	elif evt == CHG_EXT:
		changeExtension()
		Draw.Redraw()	
	
	elif evt == REDRAW:
		Draw.Redraw()
		
	elif evt == EXIT:
		Draw.Exit()
		
	else:
		print "Error: Unexpected Button Event"

def GUI():
	global NO_EVT, SINGLE_IMG, DIRECT_IMG, CLR_PATH, CHG_EXT, DO_SCRIPT, EXIT, REDRAW
	global ImagePath, imgExt, showStatus
	global matColR, matColG, matColB, matAlpha, matRef, matSpec, matHard, matZtransp, matShadeless
	global texCol, texAlpha, imgUseAlpha, imgCalcAlpha
	global viewTransp, pixelsPerUnit
	
	BGL.glClearColor(0.7, 0.7, 0.7 ,1)
	BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
	
	#Set Up Coordinates
	minx = 5
	maxx = 500
	miny = 5
	maxy = 325
	
	#Draw The Background
	BGL.glColor3f(0,0,0)
	BGL.glRecti(minx, miny, maxx, maxy)
	BGL.glColor3f(0.36, 0.95, 1.0)
	BGL.glRecti(minx+1, miny+1, maxx-1, maxy-1)
	BGL.glColor3f(0.5, 0.5, 0.5)
	BGL.glRecti(minx+2, miny+2, maxx-2, maxy-2)
	
	#Draw Title
	BGL.glColor3f(0.2, 0.2, 0.2)
	BGL.glRecti(minx+3, maxy-50, maxx-3, maxy-3)
	BGL.glColor3f(0.929, 0.782, .268)
	
	title = "2D Cutout Image Importer"
	tLength = Draw.GetStringWidth(title, "large")
	BGL.glRasterPos2i(int((maxx-minx)/2 - tLength/2), maxy-30)
	Draw.Text(title, "large")
	
	#Draw The Import Buttons
	if ImagePath.val == '':
		Draw.PushButton('Load Single Image', SINGLE_IMG, minx+4, maxy-70, 150, 19, "Import a Single Image")
		Draw.PushButton('Load Directory', DIRECT_IMG, minx+155, maxy-70, 150, 19, "Import all images in a Directory")
		BGL.glRasterPos2i(minx+4, miny+9)
		Draw.Text("You must select a valid path to be able to import images")
		
	else:
		Draw.PushButton('Clear', CLR_PATH, minx+4, maxy - 70, 50, 19, "Clear Path and allow a change of import options")
		Draw.PushButton('Import!', DO_SCRIPT, minx +4, miny+4, 50, 19, "Import image(s)")
				
	ImagePath = Draw.String('Path: ', NO_EVT, minx + 4, maxy - 90, (maxx - minx - 8), 19, ImagePath.val, 399, "Path to image to import")
	imgExt = Draw.String('Image Type: ', CHG_EXT, minx + 4, maxy - 110, 105, 19, imgExt.val, 4, "Path to image to import")
	pixelsPerUnit = Draw.Slider('Pixels Per Unit: ', NO_EVT, minx + 245, maxy - 110, 245, 19, pixelsPerUnit.val, 1, 5000, 0, "Set the number of pixels per blender unit")

	Draw.PushButton('Exit', EXIT, maxx - 54, miny+5, 50, 19, "Exit the script")
	
	#Draw Material Options Title/Box
	BGL.glColor3f(0.2, 0.2, 0.2)
	BGL.glRecti(minx+3, maxy-140, maxx-3, maxy-112)
	
	BGL.glColor3f(0.929, 0.782, .268)
	opText = "Material Options"
	tLength = Draw.GetStringWidth(opText)
	BGL.glRasterPos2i(int((maxx-minx)/2 - tLength/2), maxy-130)
	Draw.Text(opText)
	
	#Draw Options Buttons
	#Draw Color Rectangle
	BGL.glColor3f(matColR.val, matColG.val, matColB.val)
	BGL.glRecti(minx + 4, maxy - 198, minx + 29, maxy - 142)
	
	#Draw Color Sliders
	matColR = Draw.Slider('R: ', REDRAW, minx + 30, maxy - 160, 150, 19, matColR.val, 0.0, 1.0, 0, "Set the Red Value of the created material")
	matColG = Draw.Slider('G: ', REDRAW, minx + 30, maxy - 179, 150, 19, matColG.val, 0.0, 1.0, 0, "Set the Green Value of the created material")
	matColB = Draw.Slider('B: ', REDRAW, minx + 30, maxy - 198, 150, 19, matColB.val, 0.0, 1.0, 0, "Set the Blue Value of the created material")
	
	#Draw Alpha Slider
	matAlpha = Draw.Slider('Alpha: ', NO_EVT, minx + 4, maxy - 217, 176, 19, matAlpha.val, 0.0, 1.0, 0, "Set the Alpha Value of the created material")
	
	#Draw Shader Sliders
	matRef = Draw.Slider('Ref: ', NO_EVT, minx + 200, maxy - 160, 150, 19, matRef.val, 0.0, 1.0, 0, "Change the Ref Value of the created material")
	matSpec = Draw.Slider('Spec: ', NO_EVT, minx + 200, maxy - 179, 150, 19, matSpec.val, 0.0, 1.0, 0, "Change the Spec Value of the created material")
	matHard = Draw.Slider('Hard: ', NO_EVT, minx + 200, maxy - 198, 150, 19, matHard.val, 0, 511, 0, "Change the Hardness Value of the created material")
	
	#Draw Transp and Shading Options
	matZtransp = Draw.Toggle('ZTransp', NO_EVT, minx + 200, maxy - 217, 75, 19, matZtransp.val, "Enable (default)/Disable ZTransparency")
	matShadeless = Draw.Toggle('Shadeless', NO_EVT, minx + 275, maxy - 217, 75, 19, matShadeless.val, "Enable (default)/Disable Shadeless on Material (Disregards above settings)")
	
	#Draw Texture Options
	BGL.glColor3f(0.929, 0.782, .268)
	BGL.glRasterPos2i(390, maxy - 154)
	Draw.Text("Texture Settings")
	texCol = Draw.Toggle('Color', NO_EVT, minx + 366, maxy - 179, 62, 19, texCol.val, "Map To Color Channel")
	texAlpha = Draw.Toggle('Alpha', NO_EVT, minx + 428, maxy - 179, 62, 19, texAlpha.val, "Map To Alpha Channel")
	
	#Image Settings
	imgUseAlpha = Draw.Toggle('Use Alpha', NO_EVT, minx + 366, maxy - 198, 124, 19, imgUseAlpha.val, "Use the Images' Alpha Channel(s)")
	imgCalcAlpha = Draw.Toggle('Calc Alpha', NO_EVT, minx + 366, maxy - 217,124, 19, imgCalcAlpha.val, "Calculate Alpha from RGB Values")
	
	#Draw Mesh Options
	BGL.glColor3f(0.2, 0.2, 0.2)
	BGL.glRecti(minx+3, maxy-248, maxx-3, maxy-220)
	
	BGL.glColor3f(0.929, 0.782, .268)
	Text = "Display Options"
	tLength = Draw.GetStringWidth(Text)
	BGL.glRasterPos2i(int((maxx-minx)/2 - tLength/2), maxy - 238)
	Draw.Text(Text)
	
	#Viewport Display
	viewTransp = Draw.Toggle('3D Viewport Transparency', NO_EVT, minx + 150, maxy - 269, 200, 19, viewTransp.val, "Allows use of alpha channel in the 3D viewport")
	
	#Draw Execution Options
	BGL.glColor3f(0.2, 0.2, 0.2)
	BGL.glRecti(minx+3, maxy-296, maxx-3, maxy-271)
	
	BGL.glColor3f(0.929, 0.782, .268)
	Text = "Script Execution"
	tLength = Draw.GetStringWidth(Text)
	BGL.glRasterPos2i(int((maxx-minx)/2 - tLength/2), maxy - 287)
	Draw.Text(Text)

Draw.Register(GUI, event, bevent)
